package com.caissa.springboot.starter.permission.service;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @author admin
 * @date 2020/9/10 下午6:28
 */
@Slf4j
@Data
public class AesTokenUtil {
    /**
     * AES秘钥
     */
    private static String aesKeyTmp = "5216233188157728";
    /**
     * MD5盐值
     */
    private static String md5SaltTmp = "108813";
    /**
     * 有效期，单位秒
     * <p>
     * - 默认2周
     */
    private Integer expirationTimeInSecond = 1209600;
    /**
     * md5 签名长度
     */
    private static final Integer MD5_STR_LENGTH = 32;
    /**
     * token分隔符
     */
    private static final String SPLIT_STR = ".";

    public AesTokenUtil() {}

    /**
     * 解密为字符串
     *
     * @param encryptToken token
     * @return 解密内容
     */
    public static String decryptToken(String encryptToken) {
        Digester md5Digester = new Digester(DigestAlgorithm.MD5);
        md5Digester.setSalt(md5SaltTmp.getBytes());

        AES aes = SecureUtil.aes(aesKeyTmp.getBytes());
        if (StrUtil.isBlank(encryptToken)) {
            throw new SecurityException("Token is blank.");
        }

        if (encryptToken.length() < MD5_STR_LENGTH) {
            throw new SecurityException("Token length invalid.");
        }

        String decryptStr = null;
        if(encryptToken.contains(SPLIT_STR)){
            String[] splitTokens = encryptToken.split("\\.");
            if (ObjectUtil.isNotNull(splitTokens) && splitTokens.length > 1) {
                String encryptTokenFirst = splitTokens[0];
                String encryptTokenSecond = splitTokens[1];

                String digestHex = null;
                try {
                    digestHex = md5Digester.digestHex(encryptTokenSecond);
                } catch (Exception e) {
                    log.error("MD5异常加密: {}，encryptTokenFirst: {}, encryptTokenSecond: {}", e, encryptTokenFirst, encryptTokenSecond);
                    digestHex = encryptTokenFirst;
                }

                if (!ObjectUtil.equal(encryptTokenFirst, digestHex)) {
                    throw new SecurityException("Token sign invalid.");
                }
                decryptStr = aes.decryptStr(encryptTokenSecond, CharsetUtil.CHARSET_UTF_8);
            }
        } else {
            decryptStr = aes.decryptStr(encryptToken, CharsetUtil.CHARSET_UTF_8);
        }
        if (log.isDebugEnabled()) {
            log.debug("加密 Token：{}，解密内容：{}", encryptToken, decryptStr);
        }
        return decryptStr;
    }

    /**
     * 获取token中的用户信息
     *
     * @param token key
     * @return 返回结果
     */
    public static JSONObject getUserJsonObject(String token) {
        String targetContent = decryptToken(token);
        return JSONUtil.parseObj(targetContent);
    }

    public static void main(String[] args) {
        JSONObject userJsonObject = AesTokenUtil.getUserJsonObject("3fb783a6d1fd163ad348756d393b0580.8e33eaa0f8af46a83df5bf202a52195b75aaeb59bafcb61e6be803d31ea731f8fd9519710cbcafc8db527a976a0c9f3364409671c6d6290d442f40349751cc67d6e0b3c0f89cedb8855a565639cf44d43d19d57da84e7313de1c04e6997f968460bc0c3c7bf26fc6a443c3fb693cb4d2c46012ab3cdba876407977a17c32b3e1");
        System.out.println(userJsonObject);
        String str = "8e33eaa0f8af46a83df5bf202a52195b1c47be7acb522790f07bbed4b580d5c94c1f12592b7ca40eef148ec9a7f4583164409671c6d6290d442f40349751cc67d6e0b3c0f89cedb8855a565639cf44d4e412de380f52e733514b6ff7fc34f0c05ec54f106900163ce8048f3fef67c9342edfeb868e0cf9d0548d4e516976b4ab";
        Digester md5Digester = new Digester(DigestAlgorithm.MD5);
        md5Digester.setSalt(md5SaltTmp.getBytes());
        System.out.println(md5Digester.digestHex(str));
    }
}